package com.ctshk.common.utils;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

/**
 * 辅助工具类
 * 
 * @author Qiaoxin.Hong
 *
 */
public class Assist {
	
	/** 空字符串  */
	public final static String STR_EMPTY = "";
	
	/** 占位符 - {} */
	public final static String PLACEHOLDER_BRACE = "\\{\\}";
	
	/**
	 * 如果不为null，则执行action
	 * @param <T>
	 * @param val
	 * @param action
	 */
	public static <T> void consumer(T val, Consumer<T> action) {
		if (val != null) action.accept(val);
	}
	
	/**
	 * 如果不为null，则执行action
	 * @param <T>
	 * @param val
	 * @param action
	 */
	public static <T> void run(T val, Runnable action) {
		if (val != null) action.run();
	}
	
	/**
	 * 如果不为null，则执行action
	 * @param <T>
	 * @param <R>
	 * @param val
	 * @param action
	 * @return
	 */
	public static <T, R> R function(T val, Function<T, R> action) {
		return val == null ? null : action.apply(val);
	}
	
	/**
	 * 如果不为null，则执行action
	 * @param <R>
	 * @param val
	 * @param action
	 * @return
	 */
	public static <R> R supplier(Object val, Supplier<R> action) {
		return val == null ? null : action.get();
	}
	
	
	
	/**
	 * 是否为null
	 * @param val
	 * @return
	 */
	public static boolean isNull(Object val) {
		return val == null;
	}
	
	/**
	 * 是否不为null
	 * @param val
	 * @return
	 */
	public static boolean isNotNull(Object val) {
		return !isNull(val);
	}
	
	/**
	 * 是否为空
	 * @param val
	 * @return
	 */
	public static boolean isEmpty(Collection<?> val) {
		return val == null || val.size() == 0;
	}
	
	/**
	 * 是否不为空
	 * @param val
	 * @return
	 */
	public static boolean isNotEmpty(Collection<?> val) {
		return !isEmpty(val);
	}
	
	/**
	 * 是否为空
	 * @param val
	 * @return
	 */
	public static boolean isEmpty(byte[] val) {
		return val == null || val.length == 0;
	}
	
	/**
	 * 是否不为空
	 * @param val
	 * @return
	 */
	public static boolean isNotEmpty(byte[] val) {
		return !isEmpty(val);
	}
	
	/**
	 * 是否为空
	 * @param val
	 * @return
	 */
	public static boolean isBlank(Object val) {
		if (val == null) return true;
		if (val instanceof CharSequence) return StringUtils.isBlank((CharSequence) val);
		return false;
	}
	
	/**
	 * 是否不为空
	 * @param val
	 * @return
	 */
	public static boolean isNotBlank(Object val) {
		return !isBlank(val);
	}
	
	/**
	 * 是否为空
	 * @param <T>
	 * @param val
	 * @return
	 */
	public static <T> boolean isEmpty(T[] val) {
		return val == null || val.length == 0;
	}
	
	/**
	 * 是否不为空
	 * @param <T>
	 * @param val
	 * @return
	 */
	public static <T> boolean isNotEmpty(T[] val) {
		return !isEmpty(val);
	}
	
	/**
	 * 是否为空
	 * @param val
	 * @return
	 */
	public static boolean isEmpty(Map<?, ?> val) {
		return val == null || val.size() == 0;
	}
	
	/**
	 * 是否不为空
	 * @param val
	 * @return
	 */
	public static boolean isNotEmpty(Map<?, ?> val) {
		return !isEmpty(val);
	}
	
	/**
	 * 是否为true，null => false
	 * @param val
	 * @return
	 */
	public static boolean isTrue(Boolean val) {
		return val != null && val;
	}
	
	/**
	 * 是否为false，null => true
	 * @param val
	 * @return
	 */
	public static boolean isFalse(Boolean val) {
		return val != null && !val;
	}
	
	
	
	
	/**
	 * 如果不为null，则执行action
	 * @param <T>
	 * @param val
	 * @param action
	 */
	public static <T> void ifNotNull(T val, Consumer<T> action) {
		consumer(val, action);
	}
	
	/**
	 * 如果不为null，则执行action
	 * @param val
	 * @param action
	 */
	public static void ifNotNull(Object val, Runnable action) {
		run(val, action);
	}

	/**
	 * 如果不为null，则执行action
	 * @param <T>
	 * @param <R>
	 * @param val
	 * @param action
	 * @return
	 */
	public static <T, R> R ifNotNullFn(T val, Function<T, R> action) {
		return function(val, action);
	}
	
	/**
	 * 如果不为null，则执行action
	 * @param <R>
	 * @param val
	 * @param action
	 * @return
	 */
	public static <R> R ifNotNullFn(Object val, Supplier<R> action) {
		return supplier(val, action);
	}
	
	/**
	 * 如果不为blank，则执行action
	 * @param val
	 * @param action
	 */
	public static void ifNotBlank(String val, Consumer<String> action) {
		if (isNotBlank(val))
			action.accept(val);
	}
	
	/**
	 * 如果不为blank，则执行action
	 * @param action
	 */
	public static void ifNotBlank(String val, Runnable action) {
		if (isNotBlank(val))
			action.run();
	}
	
	/**
	 * 如果不为blank，则执行action
	 * @param <R>
	 * @param val
	 * @param action
	 */
	public static <R> R ifNotBlankFn(String val, Function<String, R> action) {
		return isNotBlank(val) ? action.apply(val) : null;
	}
	
	
	
	/**
	 * 不能为null，null则抛出异常
	 * @param <T>
	 * @param val
	 * @return
	 */
	public static <T> T notNull(T val) {
		return notNull(val, "参数不能为空");
	}
	
	/**
	 * 不能为null，null则抛出异常
	 * @param <T>
	 * @param val
	 * @param msg
	 * @return
	 */
	public static <T> T notNull(T val, String msg) {
		if (val == null)
			throw new RuntimeException(msg);
		return val;
	}
	
	/**
	 * 不能为blank，blank则抛出异常
	 * @param val
	 * @param msg
	 * @return
	 */
	public static String notBlank(String val) {
		return notBlank(val, "参数不能为空");
	}
	
	/**
	 * 不能为blank，blank则抛出异常
	 * @param val
	 * @param msg
	 * @return
	 */
	public static String notBlank(String val, String msg) {
		if (isBlank(val))
			throw new RuntimeException(msg);
		return val;
	}
	
	/**
	 * 不能为empty，empty则抛出异常
	 * @param <T>
	 * @param val
	 * @return
	 */
	public static <T extends Collection<?>> T notEmpty(T val) {
		notEmpty(val, "参数不能为空");
		return val;
	}
	
	/**
	 * 不能为empty，empty则抛出异常
	 * @param <T>
	 * @param val
	 * @param msg
	 * @return
	 */
	public static <T extends Collection<?>> T notEmpty(T val, String msg) {
		if (isEmpty(val))
			throw new RuntimeException(msg);
		return val;
	}
	
	
	
	
	/**
	 * 如果不为null，则forEach执行action
	 * @param <T>
	 * @param val
	 * @param action
	 */
	public static <T> void forEach(Stream<T> val, Consumer<T> action) {
		if (val != null)
			val.forEach(action);
	}
	
	/**
	 * 如果不为null，则forEach执行action
	 * @param <T>
	 * @param val
	 * @param action
	 */
	public static <T> void forEach(Collection<T> val, Consumer<T> action) {
		if (val != null)
			val.forEach(action);
	}
	
	/**
	 * 如果不为null，则forEach执行action
	 * @param <T>
	 * @param val
	 * @param action
	 */
	public static <T> void forEach(T[] val, Consumer<T> action) {
		if (val != null)
			Arrays.stream(val).forEach(action);
	}
	
	/**
	 * 如果不为null，则forEach执行action
	 * @param <K>
	 * @param <V>
	 * @param val
	 * @param action
	 */
	public static <K, V> void forEach(Map<K, V> val, BiConsumer<K, V> action) {
		if (val != null)
			val.forEach(action);
	}
	
	/**
	 * 如果不为null，则forEach执行action，并转List
	 * @param <T>
	 * @param <R>
	 * @param val
	 * @param action
	 * @return
	 */
	public static <T, R> List<R> forEachToList(Stream<T> val, Function<T, R> action) {
		return val == null ? newList() : toList(val.map(action));
	}
	
	/**
	 * 如果不为null，则forEach执行action，并转List
	 * @param <T>
	 * @param <R>
	 * @param val
	 * @param action
	 * @return
	 */
	public static <T, R> List<R> forEachToList(Collection<T> val, Function<T, R> action) {
		return val == null ? newList() : toList(val.stream().map(action));
	}
	
	/**
	 * 如果不为null，则forEach执行action，并转List
	 * @param <T>
	 * @param <R>
	 * @param val
	 * @param action
	 * @return
	 */
	public static <T, R> List<R> forEachToList(T[] val, Function<T, R> action) {
		return val == null ? newList() : toList(Arrays.stream(val).map(action));
	}
	
	/**
	 * 如果不为null，则forEach执行action，并转List
	 * @param <R>
	 * @param <K>
	 * @param <V>
	 * @param val
	 * @param action
	 * @return
	 */
	public static <R, K, V> List<R> forEachToList(Map<K, V> val, BiFunction<K, V, R> action) {
		List<R> list = newList();
		forEach(val, (k, v) -> list.add(action.apply(k, v)));
		return list;
	}
	
	/**
	 * 如果不为null，则forEach执行action，并转Map
	 * @param <T>
	 * @param <K>
	 * @param val
	 * @param keyAction key action
	 * @param valueAction value action
	 * @return
	 */
	public static <T, K> Map<K, T> forEachToMap(Collection<T> val, Function<T, K> keyAction) {
		return isEmpty(val) ? newMap() : val.stream().collect(Collectors.toMap(keyAction, item -> item));
	}
	
	/**
	 * 如果不为null，则forEach执行action，并转Map
	 * @param <T>
	 * @param <K>
	 * @param <V>
	 * @param val
	 * @param keyAction key action
	 * @param valueAction value action
	 * @return
	 */
	public static <T, K, V> Map<K, V> forEachToMap(Collection<T> val, Function<T, K> keyAction, Function<T, V> valueAction) {
		return isEmpty(val) ? newMap() : val.stream().collect(Collectors.toMap(keyAction, valueAction));
	}
	
	/**
	 * 如果不为null，则for有序执行action
	 * @param <T>
	 * @param val
	 * @param action
	 */
	public static <T> void forEachOrdered(List<T> val, BiConsumer<Integer, T> action) {
		if (isEmpty(val)) return;
		for (int i = 0; i < val.size(); i++)
			action.accept(i, val.get(i));
	}
	
	/**
	 * 如果不为null，则for有序执行action
	 * @param <T>
	 * @param val
	 * @param action
	 */
	public static <T> void forEachOrdered(T[] val, BiConsumer<Integer, T> action) {
		if (isEmpty(val)) return;
		for (int i = 0; i < val.length; i++)
			action.accept(i, val[i]);
	}
	
	

	/**
	 * 添加元素
	 * @param <T>
	 * @param val
	 * @param data
	 */
	@SuppressWarnings("unchecked")
	public static <T> void add(Collection<T> val, T...data) {
		if (val != null)
			forEach(data, val::add);
	}
	
	/**
	 * 添加元素
	 * @param <T>
	 * @param val
	 * @param data
	 */
	public static <T> void add(Collection<T> val, Collection<T> data) {
		if (val != null)
			forEach(data, val::add);
	}
	
	
	
	/**
	 * 转List
	 * @param <T>
	 * @param val
	 * @return
	 */
	public static <T> List<T> toList(Stream<T> stream) {
		return ifNotNullFn(stream, () -> stream.collect(Collectors.toList()));
	}
	
	/**
	 * 转List
	 * @param <T>
	 * @param val
	 * @return
	 */
	public static <T> List<T> toList(T[] val) {
		return ifNotNullFn(val, () -> toList(Arrays.stream(val)));
	}
	
	/**
	 * 转List
	 * @param <T>
	 * @param val
	 * @return
	 */
	public static <T> List<T> toList(Collection<T> val) {
		if (val == null) return null;
		if (val instanceof List) return (List<T>) val;
		return toList(val.stream());
	}
	
	/**
	 * 转String
	 * @param val
	 * @return
	 */
	public static String toString(Object val) {
		return val == null ? null : val.toString();
	}
	
	/**
	 * 转Integer
	 * @param val
	 * @return
	 */
	public static Integer toInteger(Object val) {
		if (val == null) return null;
		if (val instanceof Integer) return (Integer) val;
		if (val instanceof BigDecimal) return ((BigDecimal) val).intValue();
		return Integer.valueOf(val.toString());
	}
	
	/**
	 * 转Long
	 * @param val
	 * @return
	 */
	public static Long toLong(Object val) {
		if (val == null) return null;
		if (val instanceof Long) return (Long) val;
		if (val instanceof BigDecimal) return ((BigDecimal) val).longValue();
		return Long.valueOf(val.toString());
	}
	
	/**
	 * 转Double
	 * @param val
	 * @return
	 */
	public static Double toDouble(Object val) {
		if (val == null) return null;
		if (val instanceof Double) return (Double) val;
		if (val instanceof BigDecimal) return ((BigDecimal) val).doubleValue();
		return Double.valueOf(val.toString());
	}
	
	/**
	 * 转BigDecimal
	 * @param val
	 * @return
	 */
	public static BigDecimal toBigDecimal(Object val) {
		if (val == null) return null;
		if (val instanceof BigDecimal) return (BigDecimal) val;
		return new BigDecimal(toString(val));
	}
	
	/**
	 * 对象转换
	 * @param <T>
	 * @param src
	 * @param destClass
	 * @return
	 */
	public static <T> T toBean(Object src, Class<T> destClass) {
		Assist.notNull(destClass, "destClass cannot be null");
		
		if (src == null) return null;
		
		T dest = newInstance(destClass);
		copyProperties(src, dest);
		return dest;
	}
	
	/**
	 * 对象列表转换
	 * @param <T>
	 * @param srcList
	 * @param destClass
	 * @return
	 */
	public static <T> List<T> toBeanList(Collection<?> srcList, Class<T> destClass) {
		notNull(destClass, "destClass cannot be null");

		if (srcList == null) return null;

		List<T> destList = new ArrayList<>();
		for (Object src : srcList) {
			T dest = toBean(src, destClass);
			destList.add(dest);
		}

		return destList;
	}
	
	/**
	 * <pre>
	 * json转对象
	 * null => null
	 * "" => null
	 * " " => null
	 * 有值 =>  JSONObject.parseObject(json, clazz)
	 * </pre>
	 * @param <T>
	 * @param json
	 * @param clazz
	 * @return
	 */
	public static <T> T toJsonBean(String json, Class<T> clazz) {
		notNull(clazz, "clazz cannot be null");
		if (isBlank(json)) return null;
		return JSONObject.parseObject(json, clazz);
	}
	
	/**
	 * <pre>
	 * json列表转List
	 * null => null
	 * "" => null
	 * " " => null
	 * 有值 =>  JSONObject.parseObject(json, clazz)
	 * </pre>
	 * @param <T>
	 * @param jsonList
	 * @param clazz
	 * @return
	 */
	public static <T> List<T> toJsonBeanList(Collection<String> jsonList, Class<T> clazz) {
		notNull(clazz, "clazz cannot be null");
		return forEachToList(jsonList, json -> toJsonBean(json, clazz));
	}
	
	
	
	
	/**
	 * 默认字符串
	 * @param val
	 * @param defaultVal
	 * @return
	 */
	public static String defaultString(Object val) {
		return defaultString(val, STR_EMPTY);
	}
	
	/**
	 * 默认字符串
	 * @param val
	 * @param defaultVal
	 * @return
	 */
	public static String defaultString(Object val, String defaultVal) {
		return isBlank(val) ? defaultVal : val.toString();
	}
	
	/**
	 * 默认BigDecimal
	 * @param val
	 * @param defaultVal
	 * @return
	 */
	public static BigDecimal defaultBigDecimal(Number val) {
		return defaultBigDecimal(val, BigDecimal.ZERO);
	}
	
	/**
	 * 默认BigDecimal
	 * @param val
	 * @param defaultVal
	 * @return
	 */
	public static BigDecimal defaultBigDecimal(Number val, BigDecimal defaultVal) {
		return val == null ? defaultVal : toBigDecimal(defaultVal);
	}
	
	/**
	 * 默认List
	 * @param <T>
	 * @param val
	 * @return
	 */
	public static <T> List<T> defaultList(List<T> val) {
		return val == null ? newList() : val;
	}
	
	/**
	 * 默认Set
	 * @param <T>
	 * @param val
	 * @return
	 */
	public static <T> Set<T> defaultSet(Set<T> val) {
		return val == null ? newSet() : val;
	}
	
	/**
	 * 默认值0
	 * @param val
	 * @return
	 */
	public static int defaultInt(Object val) {
		if (val == null) return 0;
		if (val instanceof Integer) return (int) val;
		return Integer.valueOf(val.toString());
	}
	
	
	
	
	/**
	 * 是否小于
	 * @param val1
	 * @param val2
	 * @return
	 */
	public static <T extends Comparable<T>> boolean lt(T val1, T val2) {
		notNull(val1);
		notNull(val2);
		return val1.compareTo(val2) < 0;
	}
	
	/**
	 * 是否大于
	 * @param val1
	 * @param val2
	 * @return
	 */
	public static <T extends Comparable<T>> boolean gt(T val1, T val2) {
		notNull(val1);
		notNull(val2);
		return val1.compareTo(val2) > 0;
	}
	
	/**
	 * 是否等于
	 * @param val1
	 * @param val2
	 * @return
	 */
	public static <T extends Comparable<T>> boolean eq(T val1, T val2) {
		notNull(val1);
		notNull(val2);
		return val1.compareTo(val2) == 0;
	}
	
	/**
	 * <pre>
	 * 是否大于0
	 * null => false
	 * </pre>
	 * @param val
	 * @return
	 */
	public static boolean gtZero(BigDecimal val) {
		return gt(val, BigDecimal.ZERO);
	}
	
	/**
	 * 是否小于0
	 * @param val1
	 * @return
	 */
	public static boolean ltZero(BigDecimal val1) {
		return lt(val1, BigDecimal.ZERO);
	}
	
	/**
	 * <pre>
	 * 是否大于0
	 * null => false
	 * </pre>
	 * @param val
	 * @return
	 */
	public static boolean gtZero(Integer val) {
		return val != null && val > 0;
	}
	
	/**
	 * <pre>
	 * 是否小于0
	 * null => false
	 * </pre>
	 * @param val
	 * @return
	 */
	public static boolean ltZero(Integer val) {
		return val != null && val < 0;
	}
	
	
	
	
	
	
	/**
	 * 提取集合中的属性，并以,进行拼接，如：a,b,c
	 * @param <T>
	 * @param <R>
	 * @param vals
	 * @param action
	 * @param separator
	 * @return
	 */
	public static <T, R> String join(Collection<T> vals, Function<T, R> action) {
		return join(vals, action, BConst.COMMA);
	}
	
	/**
	 * 提取集合中的属性，并以分割符进行拼接，如：a,b,c
	 * @param <T>
	 * @param <R>
	 * @param vals
	 * @param action
	 * @param separator
	 * @return
	 */
	public static <T, R> String join(Collection<T> vals, Function<T, R> action, String separator) {
		if (isEmpty(vals)) return STR_EMPTY;
		separator = defaultString(separator);
		StringBuilder sb = new StringBuilder();
		
		if (isNotEmpty(vals)) {
			for (T val : vals) {
				if (sb.length() != 0)
					sb.append(separator);
				sb.append(defaultString(action.apply(val)));
			}
		}
		return sb.toString();
	}
	
	/**
	 * 拼接字符串
	 * @param val
	 * @return
	 */
	public static String join(Object...val) {
		StringBuilder sb = new StringBuilder();
		forEach(val, obj -> sb.append(defaultString(obj)));
		return sb.toString();
	}
	
	/**
	 * 以分割符进行拼接，如：a,b,c
	 * @param <T>
	 * @param <R>
	 * @param vals
	 * @param separator
	 * @return
	 */
	public static <T, R> String join(Collection<String> vals, String separator) {
		if (isEmpty(vals)) return STR_EMPTY;
		separator = defaultString(separator);
		StringBuilder sb = new StringBuilder();
		
		for (String val : vals) {
			if (sb.length() != 0)
				sb.append(separator);
			sb.append(defaultString(val));
		}
		return sb.toString();
	}
	
	
	
	
	/**
	 * 初始化List
	 * @param <T>
	 * @param val
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> List<T> asList(T...val) {
		List<T> list = newList();
		forEach(val, list::add);
		return list;
	}
	
	/**
	 * 初始化Map
	 * @param <T>
	 * @param arr 数量必须为偶数，键1, 值1, ..., 键n, 值n
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <K, V> Map<K, V> asMap(Object...arr) {
		Map<K, V> map = new HashMap<>();
		if (isNotEmpty(arr)) {
			if (arr.length % 2 != 0)
				throw new RuntimeException("arr length must be even");
			for (int i = 0; i < arr.length; i+=2) {
				K key = (K) arr[i];
				V value = (V) arr[i + 1];
				map.put(key, value);
			}
		}
		return map;
	}
	
	
	
	/**
	 * 过滤，并转List
	 * @param <T>
	 * @param val
	 * @param action
	 * @return
	 */
	public static <T> List<T> filterToList(Collection<T> val, Predicate<T> action) {
		if (isEmpty(val)) return newList();
		return toList(val.stream().filter(action));
	}
	
	/**
	 * 过滤出第一条符合条件的数据
	 * @param <T>
	 * @param val
	 * @param action
	 * @return
	 */
	public static <T> T filterFirst(Collection<T> val, Predicate<T> action) {
		if (isEmpty(val)) return null;
		for (T item : val) {
			if (action.test(item))
				return item;
		}
		return null;
	}
	
	/**
	 * 过滤出指定数量符合条件的数据
	 * @param <T>
	 * @param val
	 * @param action
	 * @return
	 */
	public static <T> List<T> filterToList(Collection<T> val, Predicate<T> action, int count) {
		List<T> resultList = newList();
		if (isEmpty(val) || count <= 0) return resultList;
		
		for (T item : val) {
			if (action.test(item)) {
				resultList.add(item);
				
				if (resultList.size() >= count)
					break;
			}
		}
		return resultList;
	}
	
	
	
	/**
	 * 保留两位小数，四舍五入
	 * @param val
	 */
	public static BigDecimal setScale(BigDecimal val) {
		if (val == null) return null;
		return val.setScale(2, RoundingMode.HALF_UP);
	}
	
	/**
	 * 保留整数，向上取整
	 * @param val
	 */
	public static BigDecimal setScaleIntegerUp(BigDecimal val) {
		if (val == null) return null;
		return val.setScale(0, RoundingMode.UP);
	}
	
	/**
	 * 保留两位小数，向上取整
	 * @param val
	 */
	public static BigDecimal setScaleTwoUp(BigDecimal val) {
		if (val == null) return null;
		return val.setScale(2, RoundingMode.UP);
	}
	
	/**
	 * 除
	 * @param val1
	 * @param val2
	 * @return
	 */
	public static BigDecimal divide(BigDecimal val1, Number val2) {
		if (val1 == null || val2 == null) return val1;
		return val1.divide(toBigDecimal(val2));
	}
	
	/**
	 * 除，结果保留两位小数且四舍五入
	 * @param val1
	 * @param val2
	 * @return
	 */
	public static BigDecimal divideScale(BigDecimal val1, Number val2) {
		return setScale(divide(val1, val2));
	}
	
	/**
	 * 加
	 * @param val1
	 * @param val2
	 */
	public static BigDecimal add(BigDecimal val1, Number val2) {
		if (val1 == null || val2 == null) return val1;
		return val1.add(toBigDecimal(val2));
	}
	
	/**
	 * 加
	 * @param vals
	 * @return
	 */
	public static int add(Integer...vals) {
		int result = 0;
		for (Integer val : vals) {
			if (val != null) {
				result = result + val;
			}
		}
		return result;
	}
	
	/**
	 * 减
	 * @param val1
	 * @param val2
	 */
	public static BigDecimal subtract(BigDecimal val1, Number val2) {
		if (val1 == null || val2 == null) return val1;
		return val1.subtract(toBigDecimal(val2));
	}
	
	/**
	 * 乘
	 * @param val1
	 * @param val2
	 * @return
	 */
	public static BigDecimal multiply(BigDecimal val1, Number val2) {
		if (val1 == null || val2 == null) return val1;
		return val1.multiply(toBigDecimal(val2));
	}
	
	
	
	
	/**
	 * 计算累加值
	 * @param <T>
	 * @param vals
	 * @param action
	 * @return
	 */
	public static <T> BigDecimal sumBigDecimal(Collection<T> vals, Function<T, BigDecimal> action) {
		BigDecimal num = BigDecimal.ZERO;
		forEach(vals, val -> {
			BigDecimal curNum = ifNotNullFn(val, action);
			if (curNum != null) {
				num.add(curNum);
			}
		});
		return num;
	}
	
	/**
	 * 拷贝对象
	 */
	public static void copyProperties(Object source, Object target) {
		if (target == null || source == null) return;
		BeanUtils.copyProperties(source, target);
	}
	
	/**
	 * 创建实例
	 * @param clazz
	 */
	public static <T> T newInstance(Class<T> clazz) {
		Assist.notNull(clazz, "clazz cannot be null");
		
		try {
			return clazz.getDeclaredConstructor().newInstance();
		} catch (Exception e) {
			throw new RuntimeException("new instance error", e);
		}
	}
	
	/**
	 * 创建List
	 * @param <T>
	 * @return
	 */
	public static <T> List<T> newList() {
		return new ArrayList<>();
	}
	
	/**
	 * 创建Set
	 * @param <T>
	 * @return
	 */
	public static <T> Set<T> newSet() {
		return new HashSet<>();
	}
	
	/**
	 * 创建Map
	 * @param <K>
	 * @param <V>
	 * @return
	 */
	public static <K, V> Map<K, V> newMap() {
		return new HashMap<>();
	}
	
	/**
	 * <pre>
	 * 是否相等
	 * o1 = null; o2 = null  =>  false
	 * o1 = null; o2 = 'aa'  =>  false
	 * o1 = 'aa'; o2 = null  =>  false
	 * o1 = 'aa'; o2 = 'aa'  => true
	 * o1 = 'aa'; o2 = 'bb'  => false
	 * </pre>
	 * @param o1
	 * @param o2
	 * @return
	 */
	public static boolean equals(Object o1, Object o2) {
		if (o1 == null) return o2 == null;
		if (o2 == null) return false;
		return o1.equals(o2);
	}
	
	/**
	 * 取得第一条记录
	 * @param <T>
	 * @param vals
	 * @return
	 */
	public static <T> T findFirst(Collection<T> vals) {
		if (isNotEmpty(vals))
			return vals.stream().findFirst().get();
		return null;
	}
	
	/**
	 * 取得第一条记录
	 * @param <T>
	 * @param vals
	 * @return
	 */
	public static <T> T findFirst(Map<?, T> vals) {
		if (isNotEmpty(vals)) {
			for (T val : vals.values()) {
				return val;
			}
		}
		return null;
	}
	
	/**
	 * 字符串切割，并转换为List
	 * @param str
	 * @param regex
	 * @return
	 */
	public static List<String> splitToList(Object val, String regex) {
		notBlank(regex, "regex cannot be blank");
		if (val == null) return null;
		return toList(val.toString().split(regex));
	}
	
	/**
	 * trim字符串
	 * @param val
	 * @return
	 */
	public static String trim(String val) {
		return val == null ? STR_EMPTY : val.trim();
	}
	
	/**
	 * trim字符串，并最后返回List
	 * @param val
	 * @return
	 */
	public static List<String> trimToList(Collection<String> val) {
		return forEachToList(val, Assist::trim);
	}
	
	/**
	 * trim字符串，并最后返回List
	 * @param val
	 * @return
	 */
	public static List<String> trimToList(String[] val) {
		return forEachToList(val, Assist::trim);
	}
	
	/**
	 * 从class取field，会考虑父类
	 * @param clazz
	 * @param name
	 * @return
	 */
	public static Field getDeclaredField(Class<?> clazz, String name) {
		Assist.notNull(clazz, "clazz cannot be null");
		Assist.notBlank(name, "name cannot be null");
		
		try {
			if (Object.class.equals(clazz)) return null;
			
			Field field = null;
			try {
				field = clazz.getDeclaredField(name);
			} catch (NoSuchFieldException e) {
				//未找到field不抛异常，继续找父类
			}
			if (field == null)
				field = getDeclaredField(clazz.getSuperclass(), name);
			
			return field;
		} catch (Exception e) {
			throw new RuntimeException("get declared field error", e);
		}
	}
	
	/**
	 * 排序
	 * @param <T>
	 * @param val
	 * @return
	 */
	public static <T> List<T> sorted(Collection<T> val) {
		if (isEmpty(val)) newList();
		return toList(val.stream().sorted());
	}
	
	/**
	 * 排序
	 * @param <T>
	 * @param val
	 * @return
	 */
	public static <T> List<T> sorted(Collection<T> val, Comparator<T> action) {
		if (isEmpty(val)) newList();
		return toList(val.stream().sorted(action));
	}
	
	/**
	 * 排序
	 * @param <T>
	 * @param val
	 * @return
	 */
	public static <T, R extends Comparable<R>> List<T> sorted(Collection<T> val, Function<T, R> action) {
		if (isEmpty(val)) newList();
		return toList(val.stream().sorted((o1, o2) -> {
			R v1 = action.apply(o1);
			R v2 = action.apply(o2);
			return Assist.compare(v1, v2);
		}));
	}
	
	/**
	 * 比较，考虑null
	 * @param o1
	 * @param o2
	 * @return
	 */
	public static <T extends Comparable<T>> int compare(T o1, T o2) {
		if (o1 == null) return o2 == null ? 0 : -1;
		if (o2 == null) return 1;
		return o1.compareTo(o2);
	}
	
	/**
	 * 计算百分比，val * divisor / 100
	 * @param val
	 * @param val2
	 * @return
	 */
	public static BigDecimal calcPercent(BigDecimal val, BigDecimal val2) {
		if (val == null || val2 == null) return val;
		return val.multiply(val2).divide(BConst.HUNDRED_BD);
	}
	
	/**
	 * 计算百分比，val + (val * divisor / 100)
	 * @param val
	 * @param val2
	 * @return
	 */
	public static BigDecimal calcPercentTotal(BigDecimal val, BigDecimal val2) {
		if (val == null || val2 == null) return val;
		return val.add(calcPercent(val, val2));
	}
	
	/**
	 * 计算汇率，保留两位小数，向上取整，val * rate
	 * @param val
	 * @param rate
	 * @return
	 */
	public static BigDecimal calcRateTwo(BigDecimal val, BigDecimal rate) {
		if (val == null) return val;
		notNull(rate);
		return setScaleTwoUp(multiply(val, rate));
	}
	
	/**
	 * 构建json
	 * @param <T>
	 * @param arr 数量必须为偶数，键1, 值1, ..., 键n, 值n
	 * @return
	 */
	public static String buildJson(Object...arr) {
		return JSON.toJSONString(asMap(arr));
	}
	
	/**
	 * 数量
	 * @param coll
	 * @return
	 */
	public static int size(Collection<?> coll) {
		return coll == null ? 0 : coll.size();
	}
	
	/**
	 * <pre>
	 * 以{}占位符来替换字符串
	 * 例：args = ["11", "22"]; str = "A{}BC{}D";  =>　A11BC{}D
	 * </pre>
	 * @param val
	 * @param args
	 * @return
	 */
	public static String replaceBrace(String val, Object...args) {
		if (isBlank(val) || Assist.isEmpty(args)) return val;
		
		for (Object arg : args)
			val = val.replaceFirst(PLACEHOLDER_BRACE, defaultString(arg));
		
		return val;
	}
	
	/**
	 * 构建set参数
	 * @param clazz
	 */
	public static void buildSetTxt(Class<?> clazz, String objName) {
		notNull(clazz);
		if (isBlank(objName))
			objName = "req";
		
		Field[] fields = clazz.getDeclaredFields();
		if (isEmpty(fields)) 
			return;
		for (Field field : fields) {
			if (Modifier.isStatic(field.getModifiers()))
				continue;
			String name = field.getName();
			name = name.substring(0, 1).toUpperCase() + name.substring(1);
			System.out.println(replaceBrace("{}.set{}(null);", objName, name));
		}
	}
	
	/**
	 * 从第一位开始截取字符串
	 * @param val
	 * @param length 截取长度
	 * @return
	 */
	public static String substr(String val, int length) {
		return substr(val, 0, length);
	}
	
	/**
	 * 截取字符串
	 * @param val
	 * @param beginIndex 正数：正向截；负数：反向截；
	 * @param length 截取长度
	 * @return
	 */
	public static String substr(String val, int beginIndex, int length) {
		if (val == null)
			return STR_EMPTY;
		if (length <= 0 || val.length() <= length)
			return val;
		if (beginIndex < 0)
			return val.substring(Math.abs(beginIndex) - length, beginIndex);
		else
			return val.substring(beginIndex, beginIndex + length);
	}
	
	/**
	 * 以某个属性值去重
	 * @param <T>
	 * @param <R>
	 * @param val
	 * @param action
	 * @return
	 */
	public static <T, R> List<T> distinctToList(Collection<T> val, Function<T, R> action) {
		if (val == null) return newList();
		
		List<T> resultList = newList();
		Set<R> keySet = newSet();
		
		forEach(val, item -> {
			R key = action.apply(item);
			if (!keySet.contains(key)) {
				keySet.add(key);
				resultList.add(item);
			}
		});
		
		return resultList;
	}
}
